package com.csair.irp.job.file.parser.base;

import com.csair.irp.job.common.util.MapUtil;
import com.csair.irp.job.file.exception.DataFileException;
import com.csair.irp.job.file.exception.DataOperaterException;
import com.csair.irp.job.file.exception.FileParseException;
import com.csair.irp.job.file.parser.manual.ManualTemplatePO;
import com.csair.irp.job.file.parser.manual.ManualTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * txt数据文件多行字符串对应一个数据对象解析公用流程
 * 如：AET、ATK
 *
 * @author liaolonglong
 */
public abstract class TxtFileMultiLineDataParser<T> extends BaseFileParser implements DataOperator<T> {

    /**
     * 批量入库的数据量大小
     */
    @Value("${data-file.data-insert-page-size:5000}")
    private int pageSize;

    @Autowired
    private ManualTemplateService manualTemplateService;

    @Override
    protected void doParse(File file, Serializable fileId, Map<Object, Object> params) throws DataFileException {

        String line = null;
        int lineIndex = 0;

        try (
                FileInputStream fileInputStream = new FileInputStream(file);
                InputStreamReader reader = new InputStreamReader(fileInputStream, getFileInputStreamReaderCode());
                BufferedReader bufferedReader = new BufferedReader(reader)
        ) {

            //解析每一行数据
            List<T> datas = new ArrayList<>();

            //获取模板信息
            ManualTemplatePO template = manualTemplateService.getByFileBaseinfo(MapUtil.get(params, TASK_BASE_INFO));

            int lines = template == null ? 1 : template.getColnumIndex();

            lineIndex = lines;

            //针对头几行数据做特殊处理,也可以做模板校验
            doParseHeader(bufferedReader, lines);

            T tempData = null;
            for (; ; ) {
                line = bufferedReader.readLine();
                if (line == null) {
                    if (datas.size() > 0) {
                        if (tempData != null) {
                            datas.add(tempData);
                        }
                        insertData(datas, fileId);
                    }
                    break;
                }
                lineIndex++;

                if (isIgnoreLine(line)) {
                    continue;
                }

                // 是否创建对象，如果不创建就修改已经新建对象属性
                if (isNewData(line)) {
                    if (tempData != null) {

                        //最后更新数据
                        updateDataLast(tempData, line, fileId, params);

                        //判断这条数据是否忽略，如数据去重处理
                        if (!isIgnoreData(tempData, fileId, params)) {
                            datas.add(tempData);
                        }
                        //分页入库
                        if (datas.size() == pageSize) {
                            insertData(datas, fileId);
                            datas.clear();
                        }
                    }
                    //根据行字符串创建数据对象
                    tempData = parseLineToData(line, fileId, params);
                } else {
                    updateDataByLine(tempData, line, fileId, params);
                }
            }

        } catch (FileParseException e) {
            log.error("数据文件解析异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw e;
        } catch (DataOperaterException e) {
            log.error("数据入库异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw e;
        } catch (Exception e) {
            log.error("未知异常 fileId={},lineIndex={},line={},path={}", fileId, lineIndex, line, file.getAbsolutePath(), e);
            throw new DataFileException("未知异常", e);
        }

    }

    protected boolean isIgnoreData(T data, Serializable fileId, Map<Object, Object> params) {
        return false;
    }

    /**
     * 最后更新数据对象
     *
     * @param data
     * @param line
     * @param fileId
     * @param params
     */
    protected void updateDataLast(T data, String line, Serializable fileId, Map<Object, Object> params) {
    }

    /**
     * 更新行字符串到数据对象
     *
     * @param data
     * @param line
     * @param fileId
     * @param params
     */
    protected abstract void updateDataByLine(T data, String line, Serializable fileId, Map<Object, Object> params);


    /**
     * 判断该行是否要创建一个新对象
     *
     * @param line
     * @return
     */
    protected abstract boolean isNewData(String line);

    /**
     * 处理不采集的行
     *
     * @param line
     * @return 默认不忽略所有行
     */
    protected boolean isIgnoreLine(String line) {
        return false;
    }

    /**
     * 处理数据文件头几行，如AET针对第一行数据做校验，还有手动上传的文件一般对第几列做校验
     *
     * @param bufferedReader
     * @param lines
     * @return
     */
    protected void doParseHeader(BufferedReader bufferedReader, int lines) throws DataFileException, IOException {
        //跳过前几行数据
        for (int i = 0; i < lines; i++) {
            bufferedReader.readLine();
        }
    }
}
